// 该代码给出了一个使用线程的私有数据实例，这是一个使用静态变量来累加调用结果的库函数应用
// 这种累加表现为将线程返回的字符串连接起来
/* 代码中首先预定义了下列函数用于进行对应的操作
 * char *str_accumulate(const char *s):字符串处理函数，用于将参数s传递的字符串和线程的私有数据对应的字符串连接到一起
 * static void str_alloc_key(): 这是一个创建线程私有数据的函数
 * static void str_alloc_destory_accu(void *accu):这是用于撤销线程私有数据的函数
 * void *threaddeal(void *arg):这是线程的入口函数，其主要工作是调用str_accumlate函数将arg存放的字符串和"Reault of *thread"连接到一起
 * */

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <stddef.h>

#if 0
char *str_accumulate(char *s){
	static char accu[1024] = 0;
	strcat(accu,s);
	return accu;
}
#endif

// 静态变量
static pthread_key_t str_key;		// 健值
static pthread_once_t str_alloc_key_once = PTHREAD_ONCE_INIT;	// 用于解决键冲突

static void str_alloc_key();			// 按键分配函数
static void str_alloc_destory_accu(void *accu);	// 撤销按键分配函数


// 处理函数
char *str_accumulate(const char *s){
	char *accu;
	// 解决按键冲突
	pthread_once(&str_alloc_key_once, str_alloc_key);	
	//printf("按键函数成功@\n");	//测试
	// 获取线程的私有数据地址
	accu = (char *)pthread_getspecific(str_key);
	//printf("获取线程私有数据成功!\n");	// 测试
	if(accu == NULL){
		// 给accu分配1024个地址
		accu = malloc(1024);
		//printf("分配内存函数调用成功!\n");
		if(accu == NULL){
			printf("创建内存失败!\n");
			return NULL;
		}

		accu[0] = 0;
		// 将accu存放的数据作为健值关联
		pthread_setspecific(str_key, (void *)accu);
		// 打印输出
		printf("Thread %lx: allocating buffer at %p\n", pthread_self(), accu);
		printf("-------------------------------\n");
	}

	// char* strcat(char*strDestination, const char* strSource);
	strcat(accu, s);
	return accu;
}

static void str_alloc_key(){
	// 创建健值
	pthread_key_create(&str_key, str_alloc_destory_accu);

	printf("Thread %lx: allocated key %d\n", pthread_self(), str_key);
}

// 撤销健值的函数
static void str_alloc_destory_accu(void *accu){
	printf("Thread %lx: freeing buffer at %p\n", pthread_self(),accu);
	free(accu);
}

// 线程处理函数
void *threaddeal(void *arg){
	// 该函数的主要工作是将arg的字符串和"Result of *thread"连接到一起
	char *str;
	str = str_accumulate("Result of");
	str = str_accumulate((char *)arg);
	str = str_accumulate("thread");

	printf("Thread %lx: \"%s\"\n",pthread_self(), str);
}

int main(void){
	// 创建线程标识符
	pthread_t pid1,pid2;

	char *str;

	str = str_accumulate("Result of ");

	// 创建两个线程
	pthread_create(&pid1, NULL, threaddeal, (void *)" first");
	pthread_create(&pid2, NULL, threaddeal, (void *)" second");

	str = str_accumulate("initial therad");
	printf("Thread %lx: \"%s\"\n", pthread_self(),str);

	// 阻塞两个进程
	pthread_join(pid1, NULL);
	pthread_join(pid2, NULL);

	return 0;
}


